package com.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ParseAnnotion {

    public void parseMethod(Class clazz) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException {
        Object obj = clazz.newInstance();
        Method[] methods = clazz.getDeclaredMethods();

        //Before 的注解只有一个，直接在外面定义一个Method类型的变量
        Method methodsBefore=null;
        Method[] methodsRun=null;
        int index=0;
        Method methodsAfter=null;

        //循环所有的方法
        for (Method m : methods) {
            //得到方法上的所有注解，因为不确定是Before还是After、Run，不能直接根据class得到注解
            Annotation[] myJunitTest =m.getAnnotations();
            //循环所有的注解，根据名字匹配
            for(int i=0;i<myJunitTest.length;i++){

                //根据名字匹配注解的类型
                if(myJunitTest[0].annotationType().getSimpleName().endsWith("Before")){
                    methodsBefore=m;
                }else if(myJunitTest[0].annotationType().getSimpleName().endsWith("Run")){
                    //如果为 Test ，判断这个数组是否为空，否：存入定义好的 数组中  然后下标加一
                    if(methodsRun==null){
                        //是，新生成一个数组，然后将 m 存入
                        methodsRun=new Method[ methods.length ];
                    }
                    methodsRun[index]=m;
                    index++;
                }else if(myJunitTest[0].annotationType().getSimpleName().endsWith("After")){
                    methodsAfter=m;
                }
            }

        }

        //1、先执行 Before注解的方法
        if(methodsBefore!=null){
            methodsBefore.invoke(obj);
        }
        //2、执行Run 注解的 数组中的方法
        if(methodsRun!=null && methodsRun.length>0){
            for(Method m: methodsRun){
                if(m!=null){

                    m.invoke(obj);
                }
            }
        }
        //3、最后执行 After 注解的方法
        if(methodsAfter!=null){
            methodsAfter.invoke(obj);
        }

    }

}
